
package com.trydofor.a9task.base.code.help;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.trydofor.a9task.base.code.bean.CodeLang;
import com.trydofor.a9task.base.code.bean.CodeMain;
import com.trydofor.aloe.converter.DecInteger;
import com.trydofor.aloe.exception.Exceptions;

/**
 * @author : Shi Rongjiu (www.trydofor.com)
 * @date : Nov 7, 2012
 */

public class Code {
    
    private final CodeMain               codeMain;
    private final Map<Integer, CodeLang> codeLangs = new ConcurrentHashMap<Integer, CodeLang>();
    
    /**
     * 
     * @param main the code
     * @throws NullPointerException if main is null
     */
    
    public Code(CodeMain main) {
        Exceptions.checkNullPointer(main);
        codeMain = main;
    }
    
    public CodeMain main() {
        return codeMain;
    }
    
    /**
     * add language text
     * 
     * @param lang the language to put
     * @throws NullPointerException if lang is null
     * @throws IllegalArgumentException if id is not matched
     */
    public void lang(CodeLang lang) {
        Exceptions.checkNullPointer(lang);
        Exceptions.checkIllegalArgument(lang.getCodeId() != codeMain.getId(), "id=%s,lang=%s", codeMain.getId(), lang);
        codeLangs.put(lang.getLanguage(), lang);
    }
    
    /**
     * get all langs
     * 
     * @return
     */
    public Collection<CodeLang> lang() {
        return Collections.unmodifiableCollection(codeLangs.values());
    }
    
    /**
     * get lang by langid
     * 
     * @param lang
     * @return
     */
    public CodeLang lang(Integer lang) {
        return lang(lang, null);
    }
    
    /**
     * get info by language(lang first then deft)
     * 
     * @param lang the
     * @param deft the default if lang is not found
     * @return null if not found
     */
    public CodeLang lang(Integer lang, Integer deft) {
        if (lang == null) return null;
        CodeLang l = codeLangs.get(lang);
        if (l == null && deft != null) {
            l = codeLangs.get(deft);
        }
        return l;
    }
    
    /////// helper
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(codeMain);
        for (CodeLang lang : codeLangs.values()) {
            sb.append("\n --").append(lang);
        }
        return sb.toString();
    }
    
    public int hashCode() {
        return codeMain.getId(); // code main can not null
    }
    
    public boolean equals(Object obj) {
        if (obj == null || !(obj instanceof Code)) return false;
        return hashCode() == obj.hashCode();
    }
    
    /**
     * true if get the same id
     * @param id the code id
     * @return
     */
    public boolean is(int id) {
        return codeMain.getId() == id;
    }
    
    /**
     * true if the code has the same id
     * @param cd the code
     * @return
     */
    public boolean is(Code cd) {
        if (cd == null) return false;
        return is(cd.main().getId());
    }
    
    /**
     * true if the code main has the same id
     * @param cm the code main
     * @return
     */
    public boolean is(CodeMain cm) {
        if (cm == null) return false;
        return is(cm.getId());
    }
    
    /**
     * true if the same id or key
     * @param cs the char sequnece
     * @return
     */
    public boolean is(CharSequence cs) {
        if (cs == null) return false;
        if (DecInteger.isNumber(cs)) {
            return is((int) DecInteger.number(cs));
        }
        else {
            String st = cs.toString();
            String ck = codeMain.getCodeKey();
            if (ck == null) return false;
            return st.equals(ck);
        }
    }
}
